# -*- coding: utf-8 -*-
from __future__ import unicode_literals, division
from utils.views import WdAPIView, WdListAPIView, WdRetrieveAPIView
from basic.models import ElevatorInfo, ElevatorCheckUpHistory, ElevatorYearStatistics, ElevatorFollowedByUser
from django.db.models import Count, Q, F, Sum
from utils.response import general_json_response, ErrorCode
from rest_framework import status
from users.models import CompanyInfo, CompanyPerson, AuthUser, Person
from maintenance.models import Contract, Task
import datetime
from manufacturer.models import CompanyPlatform, AuthorityCode, ElevatorFault, ElevatorMalfunction, \
    CompanyPlatformManufacturerRelation, AuthorityCodeUserRelation, Manufacturer
from serializer import ElevatorCheckUpSerializer
import json
from utils.get_codes import get_registers


class DistrictStatisticsAndDetailView(WdAPIView):
    """ 首页 区统计 区详情"""
    pass


class ElevatorSituationStatisticsView(WdAPIView):
    """ 电梯概况 统计"""
    pass


class ElevatorStatisticsForTypeView(WdAPIView):
    """电梯分类统计"""

    def get(self, request, *args, **kwargs):
        es = ElevatorInfo.objects.filter_active().values("elevator_type").annotate(count=Count("id"))
        es = list(es)
        total = sum([i['count'] for i in es])
        for item in es:
            item['percent'] = round(item['count'] * 100 / total, 2)
        return general_json_response(status.HTTP_200_OK, ErrorCode.SUCCESS, es)


class ElevatorPropertyCompanyStatisticsView(WdAPIView):
    """ 电梯使用单位统计"""
    pass


class ElevatorBrandStatisticsView(WdAPIView):
    """ 电梯品牌统计"""
    pass


class ElevatorMaintainCompanyStatisticsView(WdAPIView):
    """ 电梯维保单位统计 """
    pass


class ElevatorDetailView(WdAPIView):
    """ 电梯详情 """
    pass


class IndexStatisticsView(WdAPIView):
    """ 首页 统计 """

    def get(self, request, *args, **kwargs):
        user = self.request.user
        role = user.role
        elevators = ElevatorInfo.objects.filter_active()
        # all_elevator = elevator + 610 + 2020 + 4320
        manufacturers = Manufacturer.objects.filter_active().count()
        contract = Contract.objects.filter_active()
        years = ElevatorYearStatistics.objects.filter_active()
        if role == 0:
            maintain_company = CompanyInfo.objects.filter_active(company_type=100).count()
            property_company = CompanyInfo.objects.filter_active(company_type=300).count()
            supervisor_company = CompanyInfo.objects.filter_active(company_type=400).count()

        elif role == 20:
            maintain_company = 1
            property_company = CompanyInfo.objects.filter_active(company_type=300, service_id=user.service_id).count()
            supervisor_company = 0
            manufacturers = 0
            contract = contract.filter(service_id=user.service_id)
            years = years.filter(service_id=user.service_id)
        else:
            maintain_company = 0
            property_company = 1
            supervisor_company = 0
            manufacturers = 0
            years = years.filter(service_id=user.service_id)
            contract = contract.filter(service_id=user.service_id)

        service_contract = 0
        # company_person = CompanyPerson.objects.filter_active().count()
        aus = AuthUser.objects.filter(is_active=True, role=10)
        # contract_expire = Contract.objects.filter_active(end_time__lt=now).count()
        task = 0
        today = datetime.date.today()
        now = datetime.datetime(year=today.year, month=today.month, day=today.day)
        contract_ids = []
        for c in contract:
            end_time = datetime.datetime.strptime(c.end_time,
                                                  "%Y-%m-%d") if u"-" in c.end_time else datetime.datetime.strptime(
                c.end_time, "%Y/%m/%d")
            if end_time < now:
                contract_ids.append(c.id)

        # task_expire = Task.objects.filter_active(day__lt=today, status=10).count()
        platform = CompanyPlatform.objects.filter_active().count()
        # device = AuthorityCode.objects.filter_active().count()
        # all_device = device
        # ef = ElevatorFault.objects.filter_active().count()
        # users = AuthUser.objects.filter(is_active=True).exclude(username=u'admin').count()
        # repair_expire = ElevatorMalfunction.objects.filter_active(status__lt=50, end_planning_time__lt=today).count()

        dic = dict()
        years = years.values("year").annotate(count=Sum('number')).values("year", "count")
        print years
        for item in years:
            dic[item['year']] = item['count']
        print dic
        eis = ElevatorFollowedByUser.objects.filter_active(user=user).values_list("elevator_id", flat=True).distinct()

        rgs = ElevatorInfo.objects.filter_active(id__in=eis).values_list("register_code", flat=True).distinct()
        acs = AuthorityCode.objects.filter_active(elevator_code__in=rgs).values_list("device_code_elevator", flat=True).distinct()

        today_faults = ElevatorFault.objects.filter_active(create_time__gte=now)
        faults = ElevatorFault.objects.filter_active()
        today_tasks = Task.objects.filter_active(day=today)
        today_repair = ElevatorMalfunction.objects.filter_active(end_planning_time=today)

        my_tasks = Task.objects.filter_active(elevator__in=eis)
        my_faults = ElevatorFault.objects.filter_active(o__in=acs)
        my_repairs = ElevatorMalfunction.objects.filter_active(elevator__in=eis)

        tasks = Task.objects.filter_active()
        repair = ElevatorMalfunction.objects.filter_active()
        cp = aus.count()
        paus = AuthUser.objects.filter(is_active=True, role=30)
        pcp = paus.count()
        scp = AuthUser.objects.filter(is_active=True, role=40).count()
        if role == 20:
            cp = aus.filter(service_id=user.service_id).count()
            pcp = paus.filter(service_id=user.service_id).count()
            scp = 0
            com = user.company_person.company
            acs = AuthorityCode.objects.filter_active(maintain_company=com)
            today_tasks = today_tasks.filter(service_id=user.service_id)
            today_repair = today_repair.filter(service_id=user.service_id)
            tasks = tasks.filter(service_id=user.service_id)
            repair = repair.filter(service_id=user.service_id)
            if not user.company_person.is_admin:
                codes = get_registers(user)
                acs = acs.filter(elevator_code__in=codes)
                today_tasks = today_tasks.filter(elevator__register_code__in=codes)
                today_repair = today_repair.filter(register_code__in=codes)
                tasks = tasks.filter(elevator__register_code__in=codes)
                repair = repair.filter(register_code__in=codes)
            aos = acs.values_list("device_code_elevator", flat=True).distinct()
            faults = faults.filter(o__in=aos)
            today_faults = today_faults.filter(o__in=aos)
        elif role == 30:
            scp = 0
            cp = aus.filter(service_id=user.service_id).count()
            pcp = paus.filter(service_id=user.service_id).count()
            com = user.company_person.company
            today_tasks = today_tasks.filter(service_id=user.service_id)
            acs = AuthorityCode.objects.filter_active(property_company=com)
            today_repair = today_repair.filter(service_id=user.service_id)
            tasks = tasks.filter(service_id=user.service_id)
            repair = repair.filter(service_id=user.service_id)
            if not user.company_person.is_admin:
                codes = get_registers(user)
                acs = acs.filter(elevator_code__in=codes)
                today_tasks = today_tasks.filter(elevator__register_code__in=codes)
                today_repair = today_repair.filter(register_code__in=codes)
                tasks = tasks.filter(elevator__register_code__in=codes)
                repair = repair.filter(register_code__in=codes)
            aos = acs.values_list("device_code_elevator", flat=True).distinct()
            faults = faults.filter(o__in=aos)
            today_faults = today_faults.filter(o__in=aos)

        ios = []
        device_code_elevators = AuthorityCode.objects.filter_active().values_list("device_code_elevator", flat=True).distinct()
        for o in device_code_elevators:
            sub_qs = ElevatorFault.objects.filter_active(o=o)
            if sub_qs.count() < 5:
                continue
            alarm_time = None
            for sq in sub_qs.order_by("-id")[:5]:
                if alarm_time:
                    if not alarm_time - sq.create_time < datetime.timedelta(days=1):
                        continue
                alarm_time = sq.create_time
            ios.append(o)
        frequently_alarm_count = faults.filter(o__in=ios).count()

        three_days_later = today + datetime.timedelta(days=3)
        task_will_do = tasks.filter(result__isnull=True).count()
        task_expire = tasks.filter(day__lt=today, status=10).count()
        task_will_expire = tasks.filter(day__lte=three_days_later, day__gte=today, status=10).count()
        task_has_trouble = tasks.filter(Q(result__icontains=u"非正常") | Q(result__icontains=u"无此项")).count()

        repair_will_do = repair.filter(status__in=(0, 10)).count()
        repair_expire = repair.filter(end_planning_time__lt=today, status__lt=50).count()
        repair_will_expire = repair.filter(end_planning_time__gte=today, end_planning_time__lte=three_days_later, status__lt=50).count()

        l = ElevatorInfo.objects.filter_active(~Q(factory_no=''), manufacturer_company__isnull=False)
        if user.role in (20, 30, 40):
            service_id = user.service_id
            l = l.filter(service_id=service_id)
            elevators = elevators.filter(service_id=service_id)
            if not user.company_person.is_admin:
                codes = get_registers(user)
                l = l.filter(register_code__in=codes)
                elevators = elevators.filter(register_code__in=codes)
        elevators_unqualified = elevators.filter(inspection_conclusion__icontains=u"不合格")
        next_month = today + datetime.timedelta(days=30)
        elevators_will_expire = elevators.filter(next_yearly_inspection_date__gte=today, next_yearly_inspection_date__lte=next_month)
        elevators_expired = elevators.filter(next_yearly_inspection_date__lt=today)
        m = []
        for ei in l:
            m.append({"manufacturer_code": ei.manufacturer_company.code, "manufacturer_number": ei.factory_no})
        online_ids = []
        offline_ids = []
        for d in m:
            ac = AuthorityCode.objects.filter_active(manufacturer_code_elevator=d['manufacturer_code'],
                                                     manufacturer_number_elevator=d['manufacturer_number']).first()
            if ac:
                if ac.is_online:
                    online_ids.append(ac.id)
                else:
                    offline_ids.append(ac.id)

        # my_follow = AuthorityCodeUserRelation.objects.filter_active(user=user).count()

        data = {
            "elevator": len(eis),    # 总电梯
            # "all_elevator": 0,
            "maintain_company": maintain_company,       # 维保单位数量
            "property_company": property_company,       # 使用单位数量
            "supervisor_company": supervisor_company,       # 监管单位数量
            "company_person": cp,                       # 维保人员
            "property_person": pcp,                     # 使用单位人员
            "supervisor_person": scp,                   # 监管单位人员
            "contract": contract.count(),               # 合同数量
            "contract_expire": len(contract_ids),       # 过期合同数量
            # "task": task,
            "task_expire": task_expire,                 # 过期工单
            "task_will_do": task_will_do,               # 待处理的工单
            "task_will_expire": task_will_expire,       # 即将过期的工单
            "task_has_trouble": task_has_trouble,       # 异常的工单
            "platform": platform,                       # 平台数量
            # "device": device,
            # "all_device": all_device,
            # "ef": ef,
            # "users": users,
            # "repair": 0,
            "repair_expire": repair_expire,             # 过期维修单
            "repair_will_do": repair_will_do,           # 待处理
            "repair_will_expire": repair_will_expire,   # 即将过期
            "year_numbers": dic,
            "today_fault": today_faults.count(),        # 今日故障
            "today_tasks": today_tasks.count(),         # 今日工单
            "today_repair": today_repair.count(),       # 今日维修
            "my_follow": len(eis),                     # 我的关注
            "fault": faults.count(),                    # 故障报警
            "online_count": len(online_ids),            # 在线数量
            "offline_ids": len(offline_ids),            # 离线数量
            "frequently_alarm_count": frequently_alarm_count,                # 频繁报警数量
            "service_contract": service_contract,       # 服务合同数量
            "manufacturers": manufacturers,              # 制造单位数量
            "my_tasks": my_tasks.count(),               # 我的维保
            "my_faults": my_faults.count(),             # 我的故障
            "my_repairs": my_repairs.count(),          # 我的维修
            "elevators_unqualified": elevators_unqualified.count(),     # 检验不合格的
            "elevators_will_expire": elevators_will_expire.count(),     # 即将过期的
            "elevators_expired": elevators_expired.count(),             # 过期的

        }
        return general_json_response(status.HTTP_200_OK, ErrorCode.SUCCESS, data)


class ElevatorCheckUpListView(WdListAPIView):

    model = ElevatorInfo
    serializer_class = ElevatorCheckUpSerializer
    SEARCH_FIELDS = ("register_code", )


class ElevatorCheckUpDetailView(WdRetrieveAPIView):

    model = ElevatorInfo

    def get(self, request, *args, **kwargs):
        obj = self.get_object()
        score = 100
        number = 0

        today = datetime.datetime.now()
        that_day = today - datetime.timedelta(days=30)
        dic = {"is_online": 0, "mef": 0, "yef": 0, "task": 0, "repair": 0}
        code = obj.manufacturer_company.code if obj.manufacturer_company else None
        if code and obj.factory_no:
            ac = AuthorityCode.objects.filter_active(manufacturer_code_elevator=code,
                                                     manufacturer_number_elevator=obj.factory_no).first()
            # 是否在线
            if not ac or not ac.is_online:
                score -= 10
                number += 1
                dic['is_online'] = 1
            if ac:
                # 近30天故障
                ef_month_count = ElevatorFault.objects.filter_active(o=ac.device_code_elevator, create_time__gte=that_day).count()
                emc = ef_month_count if ef_month_count < 10 else 10
                score -= emc
                if emc:
                    number += 1
                    dic['mef'] = 1

                # 近一年故障
                that_year = today - datetime.timedelta(days=365)
                ef_year_count = ElevatorFault.objects.filter_active(o=ac.device_code_elevator, create_time__lte=that_day, create_time__gte=that_year).count()
                eyc = ef_year_count if ef_year_count < 10 else 10
                if eyc:
                    number += 1
                    dic['yef'] = 1
                score -= eyc
        else:
            score -= 10
            number += 1
            dic['is_online'] = 1
        # 电梯维保超期
        task = Task.objects.filter_active(elevator=obj).last()
        if task and task.status == 10 and task.day < today.date():
            number += 1
            score -= 10
            dic['task'] = 1
        task_end = Task.objects.filter_active(elevator=obj, result__isnull=False).last()
        if task_end:
            res = json.loads(task_end.result)
            for i in res['selects']:
                if i['ckvalue'] == u"需修理":
                    score -= 10
                    number += 1
                    dic['repair'] = 1
                    continue
        ecuh = ElevatorCheckUpHistory.objects.create(elevator=obj, score=score)
        data = {"score": score, "number": number, "crate_time": ecuh.create_time.strftime("%Y-%m-%d %H:%M:%S"),
                "result": dic}
        return general_json_response(status.HTTP_200_OK, ErrorCode.SUCCESS, data)










